class Game {
  constructor() {
    this.canvas = document.getElementById('gameCanvas')
    this.ctx = this.canvas.getContext('2d')
    this.canvas.width = 800
    this.canvas.height = 600

    this.score = 0
    this.lives = 3
    this.isRunning = false
    this.isPaused = false

    this.player = null
    this.enemies = []
    this.bullets = []
    this.walls = []

    this.keys = {}

    this.init()
  }

  init() {
    // 初始化玩家坦克
    this.player = new Tank(400, 500, 'player')

    // 初始化墙壁
    this.initWalls()

    // 初始化事件监听
    this.initEventListeners()

    // 初始化按钮事件
    this.initButtons()
  }

  initWalls() {
    // 创建一些基本的墙壁
    for (let i = 0; i < 5; i++) {
      this.walls.push(new Wall(100 + i * 150, 300))
    }
  }

  initEventListeners() {
    window.addEventListener('keydown', (e) => (this.keys[e.key] = true))
    window.addEventListener('keyup', (e) => (this.keys[e.key] = false))
  }

  initButtons() {
    document
      .getElementById('startButton')
      .addEventListener('click', () => this.start())
    document
      .getElementById('pauseButton')
      .addEventListener('click', () => this.togglePause())
  }

  start() {
    if (!this.isRunning) {
      this.isRunning = true
      this.gameLoop()
      this.spawnEnemies()
    }
  }

  togglePause() {
    this.isPaused = !this.isPaused
  }

  spawnEnemies() {
    if (this.isRunning && !this.isPaused) {
      if (this.enemies.length < 5) {
        const x = Math.random() * (this.canvas.width - 40)
        this.enemies.push(new Tank(x, 50, 'enemy'))
      }
      setTimeout(() => this.spawnEnemies(), 2000)
    }
  }

  update() {
    if (this.isPaused) return

    // 更新玩家位置
    this.updatePlayer()

    // 更新敌人
    this.updateEnemies()

    // 更新子弹
    this.updateBullets()

    // 检测碰撞
    this.checkCollisions()
  }

  updatePlayer() {
    const oldX = this.player.x
    const oldY = this.player.y

    if (this.keys['ArrowLeft']) this.player.move(-2)
    if (this.keys['ArrowRight']) this.player.move(2)
    if (this.keys['ArrowUp']) this.player.moveY(-2)
    if (this.keys['ArrowDown']) this.player.moveY(2)
    if (this.keys[' ']) this.shoot()

    // 检查玩家是否与墙壁碰撞
    if (this.checkTankWallCollision(this.player)) {
      this.player.x = oldX
      this.player.y = oldY
    }
  }

  updateEnemies() {
    this.enemies.forEach((enemy) => {
      const oldX = enemy.x
      const oldY = enemy.y

      // 计算与玩家的距离和方向
      const dx = this.player.x - enemy.x
      const dy = this.player.y - enemy.y
      const distance = Math.sqrt(dx * dx + dy * dy)

      // 根据与玩家的距离决定移动方向
      if (distance > 100) {
        // 尝试移动
        let moved = false
        const directions = [
          { dx: 1, dy: 0, dir: 1 }, // 右
          { dx: -1, dy: 0, dir: 3 }, // 左
          { dx: 0, dy: 1, dir: 2 }, // 下
          { dx: 0, dy: -1, dir: 0 }, // 上
        ]

        // 根据与玩家的相对位置对方向进行排序
        directions.sort((a, b) => {
          const distA = Math.sqrt(
            Math.pow(this.player.x - (enemy.x + a.dx * enemy.speed), 2) +
              Math.pow(this.player.y - (enemy.y + a.dy * enemy.speed), 2)
          )
          const distB = Math.sqrt(
            Math.pow(this.player.x - (enemy.x + b.dx * enemy.speed), 2) +
              Math.pow(this.player.y - (enemy.y + b.dy * enemy.speed), 2)
          )
          return distA - distB
        })

        // 尝试每个方向，直到找到一个可行的方向
        for (const dir of directions) {
          enemy.x += dir.dx * enemy.speed
          enemy.y += dir.dy * enemy.speed
          enemy.direction = dir.dir

          if (!this.checkTankWallCollision(enemy)) {
            moved = true
            break
          }

          // 如果发生碰撞，恢复位置
          enemy.x = oldX
          enemy.y = oldY
        }

        // 如果没有找到可行的方向，尝试后退
        if (!moved) {
          const backDirections = [
            { dx: -1, dy: 0, dir: 3 }, // 左
            { dx: 1, dy: 0, dir: 1 }, // 右
            { dx: 0, dy: -1, dir: 0 }, // 上
            { dx: 0, dy: 1, dir: 2 }, // 下
          ]

          for (const dir of backDirections) {
            enemy.x += dir.dx * enemy.speed
            enemy.y += dir.dy * enemy.speed
            enemy.direction = dir.dir

            if (!this.checkTankWallCollision(enemy)) {
              moved = true
              break
            }

            enemy.x = oldX
            enemy.y = oldY
          }
        }
      } else {
        // 如果距离合适，就尝试射击
        // 根据与玩家的相对位置决定朝向
        if (Math.abs(dx) > Math.abs(dy)) {
          enemy.direction = dx > 0 ? 1 : 3
        } else {
          enemy.direction = dy > 0 ? 2 : 0
        }

        // 随机射击
        if (Math.random() < 0.02) {
          this.bullets.push(
            new Bullet(
              enemy.x + enemy.width / 2,
              enemy.y + enemy.height / 2,
              'enemy',
              enemy.direction
            )
          )
        }
      }
    })
  }

  updateBullets() {
    this.bullets = this.bullets.filter((bullet) => {
      bullet.move()

      // 检查子弹是否击中墙壁
      for (const wall of this.walls) {
        if (this.checkBulletWallCollision(bullet, wall)) {
          return false
        }
      }

      return bullet.isActive
    })
  }

  checkCollisions() {
    // 检查子弹与坦克的碰撞
    this.bullets.forEach((bullet) => {
      if (bullet.owner === 'enemy' && this.player.checkCollision(bullet)) {
        this.lives--
        document.getElementById('lives').textContent = this.lives
        bullet.isActive = false // 移除击中的子弹
        if (this.lives <= 0) {
          this.gameOver()
        }
      }

      this.enemies = this.enemies.filter((enemy) => {
        if (bullet.owner === 'player' && enemy.checkCollision(bullet)) {
          this.score += 100
          document.getElementById('score').textContent = this.score
          bullet.isActive = false // 移除击中的子弹
          return false // 移除被击中的敌人
        }
        return true
      })
    })
  }

  checkBulletWallCollision(bullet, wall) {
    return (
      bullet.x < wall.x + wall.width &&
      bullet.x + bullet.width > wall.x &&
      bullet.y < wall.y + wall.height &&
      bullet.y + bullet.height > wall.y
    )
  }

  shoot() {
    if (!this.player.canShoot) return
    this.bullets.push(
      new Bullet(
        this.player.x + this.player.width / 2,
        this.player.y + this.player.height / 2,
        'player',
        this.player.direction
      )
    )
    this.player.canShoot = false
    setTimeout(() => (this.player.canShoot = true), 500)
  }

  draw() {
    // 清空画布
    this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height)

    // 绘制墙壁
    this.walls.forEach((wall) => wall.draw(this.ctx))

    // 绘制玩家
    this.player.draw(this.ctx)

    // 绘制敌人
    this.enemies.forEach((enemy) => enemy.draw(this.ctx))

    // 绘制子弹
    this.bullets.forEach((bullet) => bullet.draw(this.ctx))
  }

  gameLoop() {
    if (this.isRunning && !this.isPaused) {
      this.update()
      this.draw()
      requestAnimationFrame(() => this.gameLoop())
    }
  }

  gameOver() {
    this.isRunning = false
    alert(`游戏结束！得分：${this.score}`)
    location.reload()
  }

  checkTankWallCollision(tank) {
    return this.walls.some(
      (wall) =>
        tank.x < wall.x + wall.width &&
        tank.x + tank.width > wall.x &&
        tank.y < wall.y + wall.height &&
        tank.y + tank.height > wall.y
    )
  }
}

class Tank {
  constructor(x, y, type) {
    this.x = x
    this.y = y
    this.type = type
    this.width = 40
    this.height = 40
    this.speed = this.type === 'player' ? 5 : 3 // 敌方坦克速度稍慢
    this.canShoot = true
    this.direction = 0 // 0: 上, 1: 右, 2: 下, 3: 左
    this.lastShootTime = 0
    this.shootCooldown = this.type === 'player' ? 500 : 1000 // 敌方坦克射击冷却时间更长
    this.isInvincible = false // 添加无敌状态
    this.invincibleTime = 0 // 无敌时间
  }

  move(dx) {
    const oldX = this.x
    this.x += dx * this.speed
    this.x = Math.max(0, Math.min(800 - this.width, this.x))
    this.direction = dx > 0 ? 1 : dx < 0 ? 3 : this.direction
    return oldX !== this.x
  }

  moveY(dy) {
    const oldY = this.y
    this.y += dy * this.speed
    this.y = Math.max(0, Math.min(600 - this.height, this.y))
    this.direction = dy > 0 ? 2 : dy < 0 ? 0 : this.direction
    return oldY !== this.y
  }

  draw(ctx) {
    ctx.save()
    ctx.translate(this.x + this.width / 2, this.y + this.height / 2)
    ctx.rotate((this.direction * Math.PI) / 2)

    // 绘制坦克主体
    ctx.fillStyle = this.type === 'player' ? '#4CAF50' : '#f44336'
    ctx.fillRect(-this.width / 2, -this.height / 2, this.width, this.height)

    // 绘制炮管
    ctx.fillRect(-2, -this.height / 2 - 10, 4, 20)

    ctx.restore()
  }

  checkCollision(bullet) {
    return (
      bullet.x < this.x + this.width &&
      bullet.x + bullet.width > this.x &&
      bullet.y < this.y + this.height &&
      bullet.y + bullet.height > this.y
    )
  }
}

class Bullet {
  constructor(x, y, owner, direction) {
    this.x = x
    this.y = y
    this.owner = owner
    this.width = 4
    this.height = 8
    this.speed = 7
    this.isActive = true
    this.direction = direction // 0: 上, 1: 右, 2: 下, 3: 左
    this.createdAt = Date.now()
    this.lifetime = 3000 // 子弹存活时间3秒
  }

  move() {
    switch (this.direction) {
      case 0: // 上
        this.y -= this.speed
        break
      case 1: // 右
        this.x += this.speed
        break
      case 2: // 下
        this.y += this.speed
        break
      case 3: // 左
        this.x -= this.speed
        break
    }

    // 检查是否超出边界或超过存活时间
    if (
      this.x < 0 ||
      this.x > 800 ||
      this.y < 0 ||
      this.y > 600 ||
      Date.now() - this.createdAt > this.lifetime
    ) {
      this.isActive = false
    }
  }

  draw(ctx) {
    ctx.save()
    ctx.translate(this.x + this.width / 2, this.y + this.height / 2)
    ctx.rotate((this.direction * Math.PI) / 2)

    ctx.fillStyle = this.owner === 'player' ? '#4CAF50' : '#f44336'
    ctx.fillRect(-this.width / 2, -this.height / 2, this.width, this.height)

    ctx.restore()
  }
}

class Wall {
  constructor(x, y) {
    this.x = x
    this.y = y
    this.width = 40
    this.height = 40
  }

  draw(ctx) {
    ctx.fillStyle = '#666'
    ctx.fillRect(this.x, this.y, this.width, this.height)
  }
}

// 启动游戏
window.onload = () => {
  new Game()
}
